use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, Field, Ident};

pub fn derive_fn(input: TokenStream) -> TokenStream {
    // 解析输入并提取结构体信息
    let input = parse_macro_input!(input as DeriveInput);

    let name = &input.ident;
    let cond_name = format!("{}Condition", name.to_string());
    let cond_name = Ident::new(&cond_name, name.span());

    // 创建实现了 QueryPageCondition trait 的扩展方法
    let expanded = quote! {
        use sea_orm::*;

        pub struct #cond_name {
            filter: sea_orm::Condition,
            order_by: Vec<(Column, sea_orm::Order)>,
        }

        impl #cond_name {
            pub fn new(order_by: Vec<(Column, sea_orm::Order)>) -> Self {
                Self {
                    filter: Condition::all(),
                    order_by,
                }
            }

            pub fn get_filter(&self) -> Condition {
                self.filter.clone()
            }

            pub fn get_order_by(&self) -> Vec<(Column, sea_orm::Order)> {
                self.order_by.clone()
            }
        }

        impl #name {
            pub async fn query_page<C>(
                db: &C,
                page_num: u64,
                page_size: u64,
                condition: #cond_name,
            ) -> axum_app_common::model::PageResult<Model>
            where
                C: sea_orm::ConnectionTrait,
            {
                let mut query = Entity::find();

                let order_by = if condition.order_by.as_slice().is_empty() {
                    vec![(Column::Id, sea_orm::Order::Desc)]
                } else {
                    condition.order_by
                };

                for (col, ord) in order_by {
                    query = query.order_by(col, ord);
                }

                let query = query.filter(condition.filter);
                let query = query.paginate(db, page_size);

                let items = query.fetch_page(page_num - 1).await;
                let total = query.num_items().await;
                let items = match items {
                    Err(err) => {
                        tracing::error!("query_pages error: {}", err);
                        Vec::new()
                    }
                    Ok(items) => items,
                };

                let page = axum_app_common::model::PageResult::<Model> {
                    page_num,
                    page_size,
                    total: total.unwrap_or(0u64),
                    items,
                };

                page
            }
        }
    };

    expanded.into()
}
